import asyncore
import socket
import logging
import string
import time
import traceback

from tools import config

BUF = 1024

nodes = []

logging.basicConfig(level=logging.DEBUG,format = "%(created)-15s %(msecs)d %(levelname)8s %(thread)d %(name)s %(message)s")
log = logging.getLogger(__name__)

class Conn (asyncore.dispatcher):
	"""extended asyncore.dispatcher class"""
	
	def __init__ (self, node, parser):
		"""initial stuff, read the list of nodes"""
		asyncore.dispatcher.__init__ (self)
		self.debug = config.getDebug ()
		if self.debug :
			log.debug ("__init__")
		self.ready_to_send = False
		self.data_out = ""
		self.nodename = node[0]
		self.addr = node[1]
		self.port = node[2]
		self.write_to = ""
		self.parser = parser
		self.is_alive = False
		self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
		self.connect ((self.addr, self.port))
	
	def __getitem__ (self,fd):
		return self

	def handle_read (self) :
		"""Read from the socket, if we can."""
		if self.debug :
			log.debug ("handle_read")
		data_in = self.recv (BUF)
		if self.debug :
			log.debug ("after recv")
		if data_in :
			if self.debug :
				log.debug ("got data")
			msgs = list (string.split (data_in,"\r\n"))
			for msg in msgs:
				self.parser.parsemsg (msg,self,self.nodename)
		else :
			if self.debug :
				log.debug ("no data")
	
	def handle_write (self) :
		"""if we have something to send, we send it out"""
		if self.debug :
			log.debug ("handle_write")
		if self.data_out:
			sent = self.send (self.data_out)
			if self.debug :
				log.debug ("data sent")
			self.data_out = self.data_out[sent:]
		else:
			if self.debug :
				log.debug ("nothing to send")
		if len (self.data_out) == 0:
			self.ready_to_send = False
	
	def handle_connect (self) :
		"""connected to the node"""
		global nodes
		if self.debug :
			log.debug ("handle_connect")
		seen_this_node = True
		if self.nodename in nodes :
			self.send ("re %s\r\n" % config.getServerID())
		else:
			nodes.append (self.nodename)
			self.send ("hi %s\r\n" % config.getServerID())
		self.is_alive = True

	def handle_close (self) :
		"""handles closed sockets"""
		self.is_alive = False
		self.close ()

	def handle_expt (self) :
		"""connection failed"""
		if self.debug :
			log.debug("handle_expt")
		self.is_alive = False
		self.close ()
		time.sleep (30)
		self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
		self.connect ((self.addr, self.port))
	
	def handle_error (self) :
		""""""
		if self.debug :
			log.debug("handle_error")
			traceback.print_exc()
		self.is_alive = False
		self.close ()
		time.sleep (30)
		self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
		self.connect ((self.addr, self.port))

	def readable (self) :
		"""we always want to read"""
		return True
	
	def writable (self) :
		"""return true if we have something to send"""
		return self.ready_to_send
	
	def send_msg (self, data, to) :
		self.data_out = data
		self.ready_to_send = True

